<template>
  <div class="app">
    <h1>响应式 API:工具函数</h1>
  </div>
</template>

<script setup lang="ts" name="StuDemo5">
import { isRef, reactive, ref, toRef, toRefs, unref, type Ref } from 'vue'

let numC = 0
let dataNumC: Ref<number> = ref(0)

interface Iuser {
  name: string
  sex: string
}

interface IdataObj1<T> {
  count: number
  strArr: string[]
  user: T
}
// 深层响应性 ref
let dataObj1 = ref<IdataObj1<Iuser>>({
  count: 0,
  strArr: ['javascript', 'java', 'php', 'Arkts', 'webpack', 'go'],
  user: {
    name: 'java',
    sex: '其它'
  }
})

let dataObj2: IdataObj1<Iuser> = reactive({
  count: 0,
  strArr: ['javascript', 'java', 'php', 'Arkts', 'webpack', 'go'],
  user: {
    name: 'java',
    sex: '其它'
  }
})

// isRef()
// 检查某个值是否为 ref。
// 一层 ref
console.log(isRef(dataNumC), 'isRefNumC') //true
console.log(isRef(dataObj1), 'isRefdataObj1') //true
console.log(isRef(numC), 'isRefnumC') //false
console.log(isRef(dataObj2), 'isRefdataObj2') //false

// unref():卸载ref包装
// 如果参数是 ref，则返回内部值，否则返回参数本身。这是 val = isRef(val) ? val.value : val 计算的一个语法糖。
let newDataNumC = unref(dataNumC)
console.log(dataNumC, 'dataNumC')
console.log(newDataNumC, 'unref(dataNumC)') //卸载后为 0
function setref(data: any) {
  return isRef(data) ? data.value : data
}
console.log(setref(dataNumC))

// toRef() 会将属性变为ref响应式数据

const state1 = reactive({
  count: 0,
  name: 'Alice'
})

// 总结：
// toRef 用于提取单个属性并保持响应式。
// 它帮助你在复杂的对象结构中更灵活地操作和维护响应式数据，特别是当需要从对象中提取属性并保持响应式时。
// toRef 常用于解决解构时丢失响应性的场景。

// 使用 toRef 提取某个属性为 ref
const countRef = toRef(state1, 'count')

// 修改 ref 会更新原始对象中的属性
countRef.value = 10 // state.count 也会更新为 10

// 修改 state.count 也会影响 countRef
state1.count = 20 // countRef.value 变为 20

// toRefs
// 创建响应式对象
const state = reactive({
  count: 0,
  name: 'Alice',
  age: 25
})
const { count } = toRefs(state)
function settorefs() {
  return ++count.value
}
console.log(settorefs())
</script>

<style scoped></style>
